From: Keir Fraser Date: Tue, 3 Jun 2008 08:35:02 +0000 (+0100) Subject: x86: Enhance Cx stability by adding softirq check before entry cstate X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14200^2~103 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=7534d30b438b3ab76967743bbb162e6b60dfe823;p=xen.git x86: Enhance Cx stability by adding softirq check before entry cstate Without checking softirq_pending before entry Cx state, softirq such as SCHEDULE_SOFTIRQ and TIMER_SOFTIRQ can't be handled timely. It may cause severe failures such as disk I/O failure. This patch addresses the issue above, meanwhile move timing points closer to cstate entry/exit point to make C3 residency more accurate, and enable irq a little earlier. Signed-off-by: Wei Gang Signed-off-by: Tian Kevin --- diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c index bf81d63984..28e3e658ff 100644 --- a/xen/arch/x86/acpi/cpu_idle.c +++ b/xen/arch/x86/acpi/cpu_idle.c @@ -277,6 +277,13 @@ static void acpi_processor_idle(void) * for C2/C3 transitions. */ local_irq_disable(); + + if ( softirq_pending(smp_processor_id()) ) + { + local_irq_enable(); + return; + } + cx = power->state; if ( !cx ) { @@ -422,9 +429,6 @@ static void acpi_processor_idle(void) ACPI_FLUSH_CPU_CACHE(); } - /* Get start time (ticks) */ - t1 = inl(pmtmr_ioport); - /* * Before invoking C3, be aware that TSC/APIC timer may be * stopped by H/W. Without carefully handling of TSC/APIC stop issues, @@ -434,16 +438,19 @@ static void acpi_processor_idle(void) cstate_save_tsc(); /* preparing APIC stop */ hpet_broadcast_enter(); + + /* Get start time (ticks) */ + t1 = inl(pmtmr_ioport); /* Invoke C3 */ acpi_idle_do_entry(cx); + /* Get end time (ticks) */ + t2 = inl(pmtmr_ioport); /* recovering APIC */ hpet_broadcast_exit(); /* recovering TSC */ cstate_restore_tsc(); - /* Get end time (ticks) */ - t2 = inl(pmtmr_ioport); if ( power->flags.bm_check && power->flags.bm_control ) { /* Enable bus master arbitration */ @@ -451,10 +458,10 @@ static void acpi_processor_idle(void) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); } - /* Compute time (ticks) that we were actually asleep */ - sleep_ticks = ticks_elapsed(t1, t2); /* Re-enable interrupts */ local_irq_enable(); + /* Compute time (ticks) that we were actually asleep */ + sleep_ticks = ticks_elapsed(t1, t2); /* Do not account our idle-switching overhead: */ sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;